package com.spi.soconversion.util;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;

import com.spi.soconversion.base.SOCException;


public class ResourceProvider {
	
	private static final String XSDDIRECTORY_PATH = "xsddirectoryPath";
	private static final String XMLDIRECTORY_PATH = "xmldirectoryPath";
	private static final String LOGDIRECTORY_PATH = "logdirectoryPath";
	private static final String FETCH_OPEN_SALE_ORDER_DATA = "fetchOpenSaleOrderData";
	private static final String BATCH_SIZE = "batchSize";
	private static final String DBPASSWORD = "dbpassword";
	private static final String DBUSER = "dbuser";
	private static final String DBSERVICE = "dbservice";
	private static final String DBHOST = "dbhost";
	
	private static final String JMS_PROVIDER_URL = "jmsProviderURL";	
	private static final String JMS_IB_QUEUE_NAME = "ibQueueName";
	private static final String JMS_CSO_QUEUE_NAME = "csoQueueName";
	private static final String JMS_OSO_QUEUE_NAME = "osoQueueName";
	private static final String JMS_QUEUE_CONNECTION_FACTORY = "queueConnectionFactory";
	
	private String propertyFilePath;
	private Properties props = new Properties();
	private String timeStamp;
	
	private Connection dbConnection;
	private String xmlOutputDirectory;
	private String host;
	private String service;
	private String user;
	private String password;
	private String logFileDirectory;
	private String xsdDirectory;
	private String statisticsFile;
	
	private String fetchOpenSalesOrder;
	private int batchSize;	
	private Long returnOrderNumber;
	
	private String jmsProviderURL;
	private String ibQueueName;
	private String csoQueueName;
	private String osoQueueName;
	private String queueConnectionFactory;
	
	private static final ResourceProvider PROVIDER = new ResourceProvider();

    static private org.apache.commons.logging.Log log = 
        org.apache.commons.logging.LogFactory.getLog(ResourceProvider.class);

	private ResourceProvider() {
		try {
			setPropertyFilePath("SOConversionConfig.properties"); // testing
			init();
		} catch (SOCException e) {			
			e.printStackTrace();
			log.error("Error loading configuration properties file");
		}
	}
	
	public static ResourceProvider getInstance() {
		return PROVIDER;
	}
	
	public void init() throws SOCException {
        try {
        	// load configuration
        	props.load(new FileInputStream(getPropertyFilePath()));
		} catch (IOException e) {
			log.error("Error loading configuration properties file");
			throw new SOCException("I/O Exception occurred while reading file - " + propertyFilePath);
		}	

		// log directory
		logFileDirectory = props.getProperty(LOGDIRECTORY_PATH);
        if(logFileDirectory==null) {
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_LOG_DIRECTORY));
        }		
        
        if(!SOCUtility.checkDirectory(logFileDirectory)) {
			throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_OUTPUT_DIRECTORY) + logFileDirectory);
		}

		// initialize			
		timeStamp =  SOCUtility.dateSuffix();
		
		// xml directory
		xmlOutputDirectory = props.getProperty(XMLDIRECTORY_PATH);
        if(xmlOutputDirectory==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_XML_DIRECTORY)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_XML_DIRECTORY));
        }
        if(!SOCUtility.checkDirectory(xmlOutputDirectory)) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_OUTPUT_DIRECTORY)+xmlOutputDirectory));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_OUTPUT_DIRECTORY)+xmlOutputDirectory);
		}

        // xsd directory
		xsdDirectory = props.getProperty(XSDDIRECTORY_PATH);
        if(xsdDirectory==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_XSD_DIRECTORY)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_XSD_DIRECTORY));
        }
        if(!SOCUtility.checkDirectory(xsdDirectory)) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_OUTPUT_DIRECTORY)+xsdDirectory));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_OUTPUT_DIRECTORY)+xsdDirectory);
		}               		

        // db hostname
        host = props.getProperty(DBHOST);
        if(host==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_DATABASE_HOST)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_DATABASE_HOST));
        }		
        
        // db service name
        service = props.getProperty(DBSERVICE);
        if(service==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_DATABASE_SERVICE)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_DATABASE_SERVICE));
        }		

        // db user name
        user = props.getProperty(DBUSER);
        if(user==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_DATABASE_USER)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_DATABASE_USER));
        }		

        // db password
        password = props.getProperty(DBPASSWORD);
        if(password==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_DATABASE_PASSWORD)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_DATABASE_PASSWORD));
        }

        // batch size
        String strBatchSize = props.getProperty(BATCH_SIZE);
        if(strBatchSize==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_BATCH_SIZE)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_BATCH_SIZE));
        }

        try {
        	batchSize=Integer.parseInt(strBatchSize);    	
        
        } catch (NumberFormatException nfe) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_BATCH_SIZE)+ batchSize));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_BATCH_SIZE)+batchSize,nfe);
        }
        if(batchSize<0) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_BATCH_SIZE_NOT_POSITIVE_NUMBER) + batchSize));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_BATCH_SIZE_NOT_POSITIVE_NUMBER)+batchSize);
        }
      
        // fetch install bases        
        fetchOpenSalesOrder = props.getProperty(FETCH_OPEN_SALE_ORDER_DATA);
        if(fetchOpenSalesOrder==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.MISSING_FETCH_OSO_DATA_FLAG)));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.MISSING_FETCH_OSO_DATA_FLAG));
        }
        
        if(!"Y".equals(fetchOpenSalesOrder) && !"N".equals(fetchOpenSalesOrder)) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALLID_VALUE_FOR_FETCH_OSO_DATAONLY_FLAG) + SOCConstants.BLANK_STRING + fetchOpenSalesOrder));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALLID_VALUE_FOR_FETCH_OSO_DATAONLY_FLAG));
        }
        
        returnOrderNumber = Long.parseLong(props.getProperty("returnOrderNumber"));
        if ("".equals(returnOrderNumber)) {
        	log.error("Provide the return order number.");
        	throw new SOCException("Provide the return order number.");
        }
        
        jmsProviderURL = props.getProperty(JMS_PROVIDER_URL);
        if(jmsProviderURL==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_JMS_PROVIDER_URL) + SOCConstants.BLANK_STRING + jmsProviderURL));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_JMS_PROVIDER_URL));
        }
        
        queueConnectionFactory = props.getProperty(JMS_QUEUE_CONNECTION_FACTORY);
        if(queueConnectionFactory==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_JMS_CONNECTION_QUEUE_FACTORY) + SOCConstants.BLANK_STRING + queueConnectionFactory));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_JMS_CONNECTION_QUEUE_FACTORY));
        }
        
        
        ibQueueName = props.getProperty(JMS_IB_QUEUE_NAME);       
        if(ibQueueName==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_JMS_QUEUE_NAME_FOR_INSTALL_BASE) + SOCConstants.BLANK_STRING + ibQueueName));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_JMS_QUEUE_NAME_FOR_INSTALL_BASE));
        }

        
        csoQueueName = props.getProperty(JMS_CSO_QUEUE_NAME);     
        if(csoQueueName==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_JMS_QUEUE_NAME_FOR_CLOSED_SALES_ORDER) + SOCConstants.BLANK_STRING + csoQueueName));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_JMS_QUEUE_NAME_FOR_CLOSED_SALES_ORDER));
        }
        
        osoQueueName = props.getProperty(JMS_OSO_QUEUE_NAME);           
        if(osoQueueName==null) {
        	log.error(SOCUtility.writeLogMessage(ErrorMessageReader.getError(
    				ErrorConstants.INVALID_JMS_QUEUE_NAME_FOR_OPEN_SALES_ORDER) + SOCConstants.BLANK_STRING + osoQueueName));
        	throw new SOCException(
            		ErrorMessageReader.getError(
            				ErrorConstants.INVALID_JMS_QUEUE_NAME_FOR_OPEN_SALES_ORDER));
        }
	}
	
	public String getStatisticsFile() {
		return statisticsFile;
	}

	public void setStatisticsFile(String statisticsFile) {
		this.statisticsFile = statisticsFile;
	}

	public Connection getdbConnection() throws SOCException {
		dbConnection = DBConnection.getConnection(host, service, user, password);     
		return dbConnection;
	}
	
	public void setdBConnection(Connection dBConnection) {
		this.dbConnection = dBConnection;
	}
	
	public void closeDBConnection() throws SOCException {
		log.info("Closing the Database Connection.");
		DBConnection.closeConnection();
	}
	
	public String getXmlOutputDirectory() throws SOCException {	
		return xmlOutputDirectory;
	}
	
	public void setXmlOutputDirectory(String outputDirectory) {
		this.xmlOutputDirectory = xmlOutputDirectory + outputDirectory;
	}
	
	public String getHost() {
		return host;
	}
	
	public void setHost(String host) {
		this.host = host;
	}
	
	public String getService() {
		return service;
	}
	
	public void setService(String service) {
		this.service = service;
	}
	
	public String getUser() {
		return user;
	}
	
	public void setUser(String user) {
		this.user = user;
	}
	
	public String getPassword() {
		return password;
	}
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	public String getLogFileDirectory() {
		return logFileDirectory;
	}
	
	public void setLogFileDirectory(String logFileDirectory) {
		this.logFileDirectory = logFileDirectory;
	}
	
	public String getXsdDirectory() {
		return xsdDirectory;
	}
	
	public void setXsdDirectory(String xsdDirectory) {
		this.xsdDirectory = xsdDirectory;
	}

	public int getBatchSize() {
		return batchSize;
	}

	public void setBatchSize(int batchSize) {
		this.batchSize = batchSize;
	}

	public String getPropertyFilePath() {
		return propertyFilePath;
	}

	public void setPropertyFilePath(String propertyFilePath) {
		this.propertyFilePath = propertyFilePath;
	}

	public String getFetchOpenSalesOrder() {
		return fetchOpenSalesOrder;
	}

	public void setFetchOpenSalesOrder(String fetchOpenSalesOrder) {
		this.fetchOpenSalesOrder = fetchOpenSalesOrder;
	}

	public Long getReturnOrderNumber() {
		return returnOrderNumber;
	}

	public void setReturnOrderNumber(Long returnOrderNumber) {
		this.returnOrderNumber = returnOrderNumber;
	}

	public String getJmsProviderURL() {
		return jmsProviderURL;
	}

	public void setJmsProviderURL(String jmsProviderURL) {
		this.jmsProviderURL = jmsProviderURL;
	}

	public String getIbQueueName() {
		return ibQueueName;
	}

	public void setIbQueueName(String ibQueueName) {
		this.ibQueueName = ibQueueName;
	}

	public String getCsoQueueName() {
		return csoQueueName;
	}

	public void setCsoQueueName(String csoQueueName) {
		this.csoQueueName = csoQueueName;
	}

	public String getOsoQueueName() {
		return osoQueueName;
	}

	public void setOsoQueueName(String osoQueueName) {
		this.osoQueueName = osoQueueName;
	}

	public String getQueueConnectionFactory() {
		return queueConnectionFactory;
	}

	public void setQueueConnectionFactory(String queueConnectionFactory) {
		this.queueConnectionFactory = queueConnectionFactory;
	}
}
